import cv2
import pytesseract
import tkinter as tk
import numpy as np
from pynput.mouse import Button, Listener
from PIL import ImageGrab
from USSA1976 import *


# 鼠标点击函数
def on_click(x, y, button, pressed):
    global start_point, end_point
    if pressed and button == Button.left:
        if start_point is None:
            # 第一次点击记录起始点
            start_point = (x, y)
            print("识别起始点已添加")
        elif end_point is None:
            # 第二次点击记录结束点
            end_point = (x, y)
            print("识别终止点已添加")
            return False  # 结束监听
    if end_point is not None:
        # 输出两点坐标，并绘制矩形区域（这里仅输出坐标）
        print(f'起始点坐标: {start_point}')
        print(f'终止点坐标: {end_point}')  
    # 如果两个点都记录完毕，则停止监听
    return end_point is None



# 字符串检验函数，判断是否为数字并输出数字
def number_pick(text1):
    vel = 0
    alt = 0
    for text0 in text1:
        if is_number(text0) and vel == 0:
            vel = float(text0)
        elif is_number(text0):
            alt = float(text0)
    return vel, alt

def is_number(s):
    try:
        float(s)
        return True
    except ValueError:
        return False

#格式化输出
def format_number(num, float_precision=1):
    if abs(num) > 1e7 or (abs(num) < 1e-2 and abs(num) > 1e-5):
        #使用科学计数法
        formatted = f"{num:.{float_precision}e}"                 
    else:
        #不使用科学计数法
        formatted = f"{num:.{float_precision}f}".rstrip('.')
    return formatted

class main_widget:
    def __init__(self, root):
        self.root = root
        self.root.title("数据监控")
        self.start_point = start_point
        self.end_point = end_point
        self.filename = "result.txt"
        # 增加窗口大小
        self.root.geometry("260x400")  # 设置窗口大小
        # 初始化状态值
        self.alt = 0.0
        self.altr = 10.0    #1km间距过大，插值计算出真实高度
        self.ma = 1.0
        self.t0 = 288.15
        self.p0 = 101325.0
        self.vel = 0.0
        self.g = 0.0        #切向过载
        self.q = 0.0
        self.time = 0.0
        # 创建标签控件
        self.labels = [
            ("高度(km)", self.alt),
            # ("插值高度(km)", self.altr),
            ("马赫数Ma", self.ma),
            ("真空速(km/h)", self.vel * 3.6),
            ("真空速(m/s)", self.vel),
            ("切向过载(g)", self.g),
            ("总温(K)", self.t0),
            ("总压(Pa)", self.p0),
            ("动压(Pa)", self.q * 3.6)
        ]
        # 创建标签并布局
        self.label_widgets = []
        self.value_widgets = []
        for i, (label_text, value) in enumerate(self.labels):
            # 创建标签文本
            label = tk.Label(root, text=label_text, font=("Arial", 14))
            label.grid(row=i, column=0, sticky="e", padx=(10, 5), pady=5)  # 文本靠右对齐
            # 创建数值标签
            value_label = tk.Label(root, text=format_number(value), font=("KaiTi", 14))
            value_label.grid(row=i, column=1, sticky="w", padx=(5, 10), pady=5)  # 数值靠左对齐
            self.label_widgets.append(label)
            self.value_widgets.append(value_label)
        # 创建更新按钮
        update_button = tk.Button(root, text="停止更新", command=self.stop_update, font=("KaiTi", 14))
        update_button.grid(row=len(self.labels), columnspan=2, pady=10)
        # 设置定时更新
        self.running = True
        self.update_id = None
        self.update_data()

    def stop_update(self):
        self.running = not self.running
        self.root.children['!button'].config(text="开始更新" if not self.running else "停止更新")
        if self.update_id is not None:
            self.root.after_cancel(self.update_id)

    # 计算并更新数据
    def update_data(self):
        iter = 1        #更新次数
        if not self.running:
            return
        if self.start_point and self.end_point:
            # 截取指定范围的屏幕
            x1, y1 = self.start_point
            x2, y2 = self.end_point
            bbox = (min(x1, x2), min(y1, y2), max(x1, x2), max(y1, y2))
            screen = ImageGrab.grab(bbox=bbox)
            screen_array = np.array(screen)
            screen_array = cv2.cvtColor(screen_array, cv2.COLOR_RGB2BGR)
            # 转换为灰度图并应用阈值处理
            gray = cv2.cvtColor(screen_array, cv2.COLOR_BGR2GRAY)
            thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)[1]
            # 使用Tesseract OCR读取文本
            text = pytesseract.image_to_string(thresh, lang='eng')
            text = text.split()
            # 导出速度和高度数据
            vel, alt = number_pick(text)
            vel = vel/3.6
            # 调用大气计算程序
            atmos = USSA1976(alt)
            self.alt = alt
            self.ma = vel / atmos.a
            self.t0 = total_temperature(self.ma, atmos.t, atmos.gamma)
            self.p0 = total_pressure(self.ma, atmos.p, atmos.gamma)
            self.g = abs(vel-self.vel)/dt*1000/9.8
            self.vel = vel
            self.q = 0.5 * atmos.rho * vel ** 2.0
            # 更新标签内容
            labels = [
                ("高度(km)", self.alt),
                # ("插值高度(km)", self.altr),
                ("马赫数Ma", self.ma),
                ("真空速(km/h)", self.vel * 3.6),
                ("真空速(m/s)", self.vel),
                ("切向过载(g)", self.g),
                ("总温(K)", self.t0),
                ("总压(Pa)", self.p0),
                ("动压(Pa)", self.q * 3.6)
            ]          
            for i, (label_text, widget) in enumerate(zip(labels, self.value_widgets)):
                widget.config(text=format_number(label_text[1]))
            iter += iter
            self.time += dt/1000
        # 将数据转化为字符串形式，并写入新一行
        with open(self.filename, mode='a', encoding='utf-8') as file:
            line = f"{self.time:.5e},{alt:.5e},{vel:.5e}\n"
            file.write(line)
        # 递归调用自身
        self.update_id = self.root.after(dt, self.update_data)

# 定义变量
filename = "Starship.txt"
vel = 0
alt = 0
dt = 250    #更新周期，1000=1s
# 定义识别范围
start_point = None
end_point = None

# 执行部分
print("请依次点击识别区域[左上角]和[右下角]")
with Listener(on_click=on_click) as listener:
    listener.join()
print("区域添加完毕")
i = input("输入任意键继续")
# 创建主窗口
root = tk.Tk()
app = main_widget(root)
# 运行主循环
root.mainloop()


